/*
 * @Description:
 * @Date: 2022-11-07 16:09:11
 * @LastEditors: czp
 * @LastEditTime: 2023-05-09 11:04:22
 */

import { EApiResult } from "@/enums/appEnum";
import { useVR } from "@/hook/useVR";
import router from "@/router";
import { IBaseResp } from "@/service/interface/base";
import { useBaseStore } from "@/store/base";
import { AxiosRequestConfig, AxiosResponse, AxiosError, InternalAxiosRequestConfig } from "axios";
import axios from "axios";
// import { showToast } from "vant";

import { showFullScreenLoading, tryHideFullScreenLoading } from "../element/prompt";
import { getBaseUrl } from "../env";

class Axios {
	// axios 实例
	private instance;
	constructor(config: AxiosRequestConfig) {
		const baseConfig = this.getBaseConfig();
		this.instance = axios.create({ ...baseConfig, ...config });
		this.interceptors();
	}
	private getBaseConfig(): AxiosRequestConfig {
		return {
			baseURL: getBaseUrl(),
			headers: {
				"Access-Control-Allow-Origin": "*",
				"Content-Type": "application/json"
			}
		};
	}

	/**
	 * @description: 拦截器
	 * @return {void}
	 * @Date: 2022-09-04 15:33:53
	 */
	private interceptors() {
		this.requestHandler();
		this.responseHandler();
	}
	/**
	 * @description: 请求拦截
	 * @return {void}
	 * @Date: 2022-09-04 15:33:42
	 */
	private requestHandler() {
		this.instance.interceptors.request.use((config: InternalAxiosRequestConfig) => {
			// * 如果当前请求不需要显示 loading,在 api 服务中通过指定的第三个参数: { headers: { noLoading: true } }来控制不显示loading
			config.headers.get("noLoading") || showFullScreenLoading();
			const { token } = useBaseStore();
			config.headers.set("token", token);
			return config;
		}, this.errorHandler);
	}

	/**
	 * @description: 响应拦截
	 * @return {void}
	 * @Date: 2022-09-04 15:40:32
	 */
	private responseHandler() {
		this.instance.interceptors.response.use((res: AxiosResponse<IBaseResp<any>, AxiosRequestConfig>) => {
			tryHideFullScreenLoading();
			// token 超时
			if (res.data.code && res.data.code === EApiResult.TOKEN_ERROR) {
				ElNotification({ type: "error", message: res.data.message });
				return Promise.reject(res.data.message);
				const { login } = useVR();
				login();
			}
			// 无访问权限
			if (res.data.code && res.data.code === EApiResult.PERMISSION_ERROR) {
				router.replace("/403");
			}
			if (res.data.code == EApiResult.ERROR) {
				ElNotification({ type: "error", message: res.data.message });
				return Promise.reject(res.data.message);
			}
			if (res.data.code == EApiResult.SUCCESS) return res;
		}, this.errorHandler);
	}

	private errorHandler(error: AxiosError): Promise<AxiosError> {
		if (error && error.response) {
			switch (error.response.status) {
				case 400:
					error.message = "请求错误(400)";
					break;
				case 401:
					error.message = "未授权，请重新登录(401)";
					break;
				case 403:
					error.message = "拒绝访问(403)";
					break;
				case 404:
					error.message = "请求出错(404)";
					break;
				case 408:
					error.message = "请求超时(408)";
					break;
				case 500:
					error.message = "服务器错误(500)";
					break;
				case 501:
					error.message = "服务未实现(501)";
					break;
				case 502:
					error.message = "网络错误(502)";
					break;
				case 503:
					error.message = "服务不可用(503)";
					break;
				case 504:
					error.message = "网络超时(504)";
					break;
				case 505:
					error.message = "HTTP版本不受支持(505)";
					break;
				default:
					error.message = `连接出错(${error.response.status})!`;
			}

			// showToast({
			// 	type: "fail",
			// 	message: error.message,
			// 	duration: 2000
			// });
			// console.log(error.message);
		}
		return Promise.reject(error);
	}

	public async request<T = any, D = IBaseResp<T>>(config: AxiosRequestConfig) {
		try {
			const resp = await this.instance.request<D>(config);
			return resp.data as Promise<D>;
		} catch (error) {
			ElNotification({ type: "error", message: error.toString() });
			throw new Error(error.toString());
		}
	}
}
export default Axios;
